﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using OpenNLP.Tools.NameFind;
using OpenNLP.Tools.SentenceDetect;

namespace LSA.Framework
{
    public class EntitiesAnalyzer
    {
        private static object locker = new object();
        public async static Task<Dictionary<string, byte>> FindEntities(string[] fileNames, Action<int> enlargeBar, Action<int> fillBar)
        {
            var path = @"Models\";
            var sentenceDetector = new EnglishMaximumEntropySentenceDetector(path + "EnglishSD.nbin");
            Dictionary<string, byte> entities = new Dictionary<string, byte>();

            EnglishNameFinder finder = new EnglishNameFinder(path + "namefind\\");

            string[] categories = new[]
                                                  {
                                                      "date", "location",
                                                      "organization", "person",
                                                      "time"
                                                  };
            string[] regexes = new[]
                                   {
                                       @"<location>(.*?)</location>", @"<organization>(.*?)</organization>",
                                       @"<person>(.*?)</person>"
                                   };

            await TaskEx.Run(delegate
                                 {
                TaskEx.Run(() => enlargeBar(fileNames.Length));
                foreach (string fileName in fileNames)
                {
                    using (StreamReader stream = File.OpenText(fileName))
                    {
                        string line;
                        while ((line = stream.ReadLine()) != null)
                        {
                            string[] sentances = sentenceDetector.SentenceDetect(line);
                            foreach (string sentance in sentances)
                            {
                                var tagged = finder.GetNames(categories, sentance);
                                for (int i = 0; i < regexes.Length; i++)
                                {
                                    foreach (Match match in Regex.Matches(tagged, regexes[i]))
                                    {
                                        var value = match.Groups[1].Value;
                                        if (value.Contains("<"))
                                        {
                                            value = Regex.Replace(value, @"(<(.*?)>)", @"");
                                        }
                                        entities[value.Trim().Replace("  ", " ").Replace("\"", "")] = (byte) i;
                                    }
                                }
                            }
                        }
                    }
                    TaskEx.Run(() => fillBar(1));
                }
            });

            return
                entities.Keys.OrderByDescending(x => x.Length).Select(
                    x => new KeyValuePair<string, byte>(x, entities[x])).ToDictionary(pair => pair.Key,
                                                                                      pair => pair.Value);
        }
    }
}
